跳到主要内容

HTTPS 的代理 CONNECT 通道

CONNECT 方法:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。通常用于 SSL 加密服务器的链接(经由非加密的 HTTP 代理服务器)。

connect 方法的通常就是把服务器作为跳板机,让服务器直接代理客户端访问,然后把数据原原本本的返回给客户端,connect 方法的原理就是 TCP 直连。

HTTP CONNECT 通道

为了确保数据通信的安全,HTTPS 已广泛应用于互联网,浏览器与服务器之间的 HTTPS 通信都是加密的。然而当浏览器需要通过代理服务器发起 HTTPS 请求时,由于请求的站点地址和端口号都是加密保存于 HTTPS 请求头中的,代理服务器是如何既确保通信是加密的(代理服务器自身也无法读取通信内容)又知道该往哪里发送请求呢?

为了解决这个问题,浏览器需要先通过明文 HTTP 形式向代理服务器发送一个 CONNECT 请求告诉它目标站点地址及端口号。当代理服务器收到这个请求后,会在对应的端口上与目标站点建立一个 TCP 连接,连接建立成功后返回一个 HTTP 200 状态码告诉浏览器与该站点的加密通道已建成。接下来代理服务器仅仅是来回传输浏览器与该服务器之间的加密数据包,代理服务器并不需要解析这些内容以保证 HTTPS 的安全性。

代理 HTTPS

HTTPS 连接代理会使用到 HTTP CONNECT 通道,具体看网络基础那部分,总之就是因为 HTTPS 是加密的,所以浏览器需要先通过明文 HTTP 形式向代理服务器发送一个 CONNECT 请求告诉它目标站点地址及端口号。

普通的 HTTP 代理如下:

HTTPS 代理先走 HTTP CONNECT 通道:

使用 HTTP CONNECT 方法。它告诉代理服务器与目标服务器建立 TCP 连接,并在连接完成时代理客户机之间的 TCP 流。这种代理服务器不会终止 SSL,而是简单地在客户端和目标服务器之间传递数据,这样双方就可以建立安全连接。

HTTPS 代理中 CONNECT 方法代理步骤

  • 用户向代理发起 CONNECT 请求;
  • 代理向 Targe 发起 TCP 连接请求;
  • 代理向用户返回 “HTTP/1.0 OK\r\n\r\n”,隧道建立完成;
  • 代理转发用户的数据给 Target,转发 Target 的数据给用户,直到任何一方连接结束;

如下图所示:

示例

这里我们以 Fiddler 作为代理服务器,浏览器访问 https://www.microsoft.com/ 作为例子:

1、首先浏览器向代理服务器发送 CONNECT 请求:

CONNECT www.microsoft.com:443 HTTP/1.0
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: www.microsoft.com
Content-Length: 0
DNT: 1
Connection: Keep-Alive
Pragma: no-cache

2、代理服务器返回 HTTP 200 状态台码表示连接已建立:

HTTP/1.0 200 Connection Established
FiddlerGateway: Direct
StartTime: 11:56:22.008
Connection: close
EndTime: 11:56:22.538
ClientToServerBytes: 1416
ServerToClientBytes: 1358

3、之后浏览器和服务器开始 HTTPS 握手并交换加密数据,Fiddler 作为代理服务器只负责传输彼此的数据包,并不能读取具体数据内容(除非开启了 Fiddler 的解密 HTTPS 的功能并安装 Fiddler 根证书)。从 Wireshark 抓包中可以看出,在第 12 帧 HTTP/1.0 200 返回后,浏览器就开始建立 TLS 连接了。

References

go tls实现TLS 服务器和客户端通讯 HTTP(S) Proxy in Golang in less than 100 lines of code 理解HTTP CONNECT通道 HTTP、HTTPS代理分析及原理